package com.example.rpc_core.proxy;
import cn.hutool.core.collection.CollUtil;
import com.example.rpc_core.RpcApplication;
import com.example.rpc_core.config.RpcConfig;
import com.example.rpc_core.constance.RpcConstant;
import com.example.rpc_core.loadbalance.LoadBalancer;
import com.example.rpc_core.loadbalance.LoadBalancerFactory;
import com.example.rpc_core.model.RpcRequestExample;
import com.example.rpc_core.model.RpcResponseExample;
import com.example.rpc_core.model.ServiceInfo;
import com.example.rpc_core.register.Register;
import com.example.rpc_core.register.RegistryFactory;
import com.example.rpc_core.servers.TcpClient;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class TcpServiceProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 指定序列化器
//        final Serializable serializer = SerializableFactory.getSerializable(RpcApplication.getRpcConfig().getSerializable());
        // 构造请求
        String serviceName = method.getDeclaringClass().getName();
        RpcRequestExample rpcRequest = RpcRequestExample.builder()
                .serviceName(serviceName)
                .methodName(method.getName())
                .parameterTypes(method.getParameterTypes())
                .args(args)
                .build();
        try {
            // 从注册中心获取服务提供者请求地址
            RpcConfig rpcConfig = RpcApplication.getRpcConfig();
            Register registry = RegistryFactory.getRegistry(rpcConfig.getRegistryConfig().getRegistryType());
            ServiceInfo serviceInfo = new ServiceInfo();
            serviceInfo.setServiceName(serviceName);
            serviceInfo.setServiceVersion(RpcConstant.DEFAULT_CONFIG_Version);
            List<ServiceInfo> serviceMetaInfoList = registry.serviceDiscovery(serviceInfo.getServiceKey());
            if (CollUtil.isEmpty(serviceMetaInfoList)) {
                throw new RuntimeException("未找到服务");
            }
            //实现负载均衡
            LoadBalancer loadBalancer = LoadBalancerFactory.getLoadBalancer(rpcConfig.getLoadBalance());
            //将请求路径作为负载均衡参数
            Map<String,Object> requestParam = new HashMap<>();
            requestParam.put("methodName",rpcRequest.getMethodName());
            ServiceInfo selectedServiceInfo = loadBalancer.select(requestParam,serviceMetaInfoList);
            //发送RPC请求
            RpcResponseExample rpcResponseExample = TcpClient.doRequest(rpcRequest, selectedServiceInfo);
            return rpcResponseExample.getData();
        } catch (Exception e) {
            throw new RuntimeException("调用失败");
        }
    }
}

